from os import linesep
import random

from zope.interface import implements

from twisted.plugin import IPlugin

from toneedu.midi import midi
from toneedu.interfaces import ITonePlugin
from toneedu.exceptions import PluginError
from toneedu.util import joinLines

import chords_data

class InvalidOption(PluginError):
    def __init__(self, *args):
        super(InvalidOption, self).__init__(*args)
        self.message = args[0]

class ChordsPlugin(object):
    implements(ITonePlugin, IPlugin)
    
    def __init__(self):
        self._data = chords_data.names['interval'][0]
        self._mode = 'interval'
        
        self._random = random.Random()
        self._random.seed()

        self._last = None

        self.name = "Chords"
        self.description = "Practice the recognition of intervals, 3-chords and 4-chords"

        self.delay = 200
        self.base_min = 48
        self.base_max = 72
        self.options = ["delay", "base_min", "base_max"]
        self.modes = ["interval", "3-chord", "4-chord", "modal scale"]

    def getQuestion(self):
        base = self._random.randint(self.base_min, self.base_max)
        variation = self._random.randint(0, len(self._data) - 1)
        distances = self._data[variation][2]
        chord = [base]
        for dist in distances:
            chord.append(chord[-1] + dist)

        self._last = (variation, chord)
        return self.tryAgain()

    def checkAnswer(self, answer):
        variation, chord = self._last

        answers = self._data[variation][0] + self._data[variation][1]
        if answer in answers:
            return True
        else:
            return False

    def tryAgain(self):
        variation, chord = self._last
        midi.playChord(chord, self.delay)
        return "What %s was this?" % self._mode

    def getAnswer(self):
        variation, chord = self._last
        answer = " or ".join(self._data[variation][0])

        return "The solution is: %s" % answer

    def setOption(self, key, value):
        response = []

        if key in self.options:
            try:
                self.__setattr__(key, int(value))
            except Exception, e:
                raise InvalidOption("Please give a number as value. See help for more information")
            response = ["OK!"]
            response.append(self.getQuestion())
        elif key == "mode":
            print value
            if value not in self.modes:
                raise InvalidOption("There is no such a mode. Check the help for more information")
            self._mode = value
            self._data = chords_data.names[value][0]
            self.delay = chords_data.names[value][1]
            response.append("OK!")
            response.append(self.getQuestion())
        else:
            raise InvalidOption("There is no such a setting. Check the help for more information")
        
        return joinLines(response)

    def getOptions(self):
        return {
            "mode":     "Sets the mode which the plugin should work. Possible values: interval, 3-chord, 4-chord, modal scale",
            "delay":    "The delay in miliseconds between the notes during playing them",
            "base_min": "Sets the lowest note which can be the base of a chord. It's value is 0-127, 60 is the Middle C",
            "base_max": "Sets the highest note which can be the base of a chord"
        }
    
    def getAnswers(self):
        return [(short, long) for (short, long, dist) in self._data]
    
    def getHelp(self):
        return self.description


chordsPlugin = ChordsPlugin()

